import 'whatwg-fetch';

var objectToQueryString = function(obj) {
	var qs = _.reduce(obj, function(result, value, key) {
			return (!_.isNull(value) && !_.isUndefined(value)) ? (result += key + '=' + value + '&') : result;
	}, '').slice(0, -1);
	return qs;
};


function parseData(url, method, opts, data) {
  if ('post' === method) {
    opts.body = JSON.stringify(data);
  } else {
    url = `${url}?${objectToQueryString(data)}`;
  }
  return {
    url,
    opts
  };
}

function getRequestOpts(urlObj, data) {
  // @TODO 检查method url是否正确
  let { method, url, timeout } = urlObj;
  if (['get', 'post'].indexOf(method) < 0) {
    throw new Error(`send request error, method should be get or post, but got ${method}, request url: ${url}`);
  }

  let opts = {
    method,
    timeout,
    headers: {
      'Content-Type': 'application/json'
    },
  };
  let result = {
    url,
    opts
  };
  if (_.isObject(data)) {
    result = parseData(url, method, opts, data);
  }
  return result;
}

function sendRequest(urlObj, data) {
  const { url, opts } = getRequestOpts(urlObj, data);
  return fetch(url, opts)
    .then(response => {
      return response.json();
    })
    .then(respJson => {
      const { errorno, errmsg, data } = respJson;
      switch(errorno) {
        // 成功
        case 0:
          return data;
        default:
          let error = new Error(errmsg);
          error.data = data;
          throw error;
      };
    });
}


export default store => next => action => {
  const { reqData, apiKey, reqOpts } = action;
  if (!reqOpts) {
    return next(action);
  }
  const [requestType, successType, failureType] = reqOpts.types;
  next({type: requestType});
  sendRequest(reqOpts, reqData).then( data => {
    next({
      type: successType,
      data
    });
  }).catch(err => {
    const { message, data } = err;
    next({
      type: failureType,
      errorMsg: message,
      data
    })
  })
}
